So far, we've dealt with individual controls, each one with a distinctive name and a distinct set of properties and events. In addition to these, Visual Basic embodies the concept of control arrays, in which multiple controls share the same set of event procedures even though each individual element in the array can have different values for its properties. A control array can be created only at design time, and at the very minimum at least one control must belong to it. You create a control array following one of these three methods:
Control arrays are one of the most interesting features of the Visual Basic environment, and they add a lot of flexibility to your programs:
The importance of using control arrays as a means of dynamically creating new controls at run time is somewhat reduced in Visual Basic 6, which has introduced a new and more powerful capability. Read about dynamic control creation in Chapter 9.
Don't let the term array lead you to think control array is related to VBA arrays; they're completely different objects. Control arrays can only be one-dimensional. They don't need to be dimensioned: Each control you add automatically extends the array. The Index property identifies the position of each control in the control array it belongs to, but it's possible for a control array to have holes in the index sequence. The lowest possible value for the Index property is 0. You reference a control belonging to a control array as you would reference a standard array item:
Text1(0).Text = "" |
Event procedures related to items in a control array are easily recognizable because they have an extra Index parameter, which precedes all other parameters. This extra parameter receives the index of the element that's raising the event, as you can see in this example:
Private Sub Text1_KeyPress(Index As Integer, KeyAscii As Integer) MsgBox "A key has been pressed on Text1(" & Index & ") control" End Sub |
The fact that multiple controls can share the same set of event procedures is often in itself a good reason to create a control array. For example, say that you want to change the background color of each of your TextBox controls to yellow when it receives the input focus and restore its background color to white when the user clicks on another field:
Private Sub Text1_GotFocus(Index As Integer) Text1(Index).BackColor = vbYellow End Sub Private Sub Text1_LostFocus(Index As Integer) Text1(Index).BackColor = vbWhite End Sub |
Control arrays are especially useful with groups of OptionButton controls because you can remember which element in the group has been activated by adding one line of code to their shared Click event. This saves code when the program needs to determine which button is the active one:
' A module-level variable Dim optFrequencyIndex As Integer Private Sub optFrequency_Click(Index As Integer) ' Remember the last button selected. optFrequencyIndex = Index End Sub |
Once you have created a control array at design time, even with just one item, it's straightforward to create new items at run time using the Load command:
' Suppose you created Text(0) at design time. Load Text1(1) ' Move the new control where you need it, and resize it. Text1(1).Move 1200, 2000, 800, 350 ' Set other properties as required. Text1(1).MaxLength = 10 ... ' Finally make it visible. Text1(1).Visible = True |
The Load command creates the new control with exactly the same set of properties that the first item of the array—Text1(0) in the preceding example—had at design time, including the position on the form. The only exception to this rule is that the Visible property for a control created in this way is always False because Visual Basic correctly expects that you want to move the new control to a different position before making it visible. Once you have dynamically added a control, it belongs to the control array and can be treated exactly like those controls created at design time.
You can remove controls from a control array using the Unload command, as in the following line of code:
Unload Text1(1) |
You can unload only controls that were added dynamically at run time; if you use the Unload command on an item of the array that had been created at design time, an error occurs. If you unload an item and then reload an item with the same index, you're actually creating a brand-new instance, which inherits its properties, size, and position from the first element in the array, as I explained previously.
Control arrays often let you save many lines of code because you can execute the same statement, or group of statements, for every control in the array without having to duplicate the code for each distinct control. For example, you can clear the contents of all the items in an array of TextBox controls as follows:
For i = txtFields.LBound To txtFields.UBound txtFields(i).Text = "" Next |
Here you're using the LBound and UBound methods exposed by the control array object, which is an intermediate object used by Visual Basic to gather all the controls in the array. In general, you shouldn't use this approach to iterate over all the items in the array because if the array has holes in the Index sequence an error will be raised. A better way to loop over all the items of a control array is using the For Each statement:
Dim txt As TextBox For Each txt In txtFields txt.Text = "" Next |
A third method exposed by the control array object, Count, returns the number of elements it contains. It can be useful on several occasions (for example, when removing all the controls that were added dynamically at run time):
' This code assumes that txtField(0) is the only control that was ' created at design time (you can't unload it at run time). Do While txtFields.Count > 1 Unload txtFields(txtFields.UBound) Loop |
Control arrays are especially useful with menus because arrays offer a solution to the proliferation of menu Click events and, above all, permit you to create new menus at run time. An array of menu controls is conceptually similar to a regular control array, only you set the Index property to a numeric (non-negative) value in the Menu Editor instead of in the Properties window.
There are some limitations, though: All the items in an array of menu controls must be adjacent and must belong to the same menu level, and their Index properties must be in ascending order (even though holes in the sequence are allowed). This set of requirements severely hinders your ability to create new menu items at run time. In fact, you can create new menu items in well-defined positions of your menu hierarchy—namely, where you put a menu item with a nonzero Index value—but you can't create new submenus or new top-level menus.
Now that you have a thorough understanding of how Visual Basic's forms and controls work, you're ready to dive into the subtleties of the Visual Basic for Applications (VBA) language. The next chapter is devoted to the many data types you can use in your programs. In Chapter 5, I illustrate the many VBA functions and commands.